package com.eastfair.projectcore.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.eastfair.auth.api.AuthServiceFeign;
import com.eastfair.auth.api.RoleServiceFeign;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.dto.OrganizationDTO;
import com.eastfair.auth.dto.OrganizationRoleDto;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.dto.UserOrganizationDTO;
import com.eastfair.auth.entity.Organization;
import com.eastfair.auth.enumeration.ResourceOrganizationResourceTypeEnum;
import com.eastfair.auth.vo.RoleVo;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.context.ContextUtil;

import com.eastfair.model.DataIsolationVo;
import com.eastfair.projectcore.dao.ProjectDbMapper;
import com.eastfair.projectcore.dto.ProjectDbDTO;
import com.eastfair.projectcore.entity.DataIsolation;
import com.eastfair.projectcore.entity.ProjectDb;
import com.eastfair.projectcore.service.DataIsolationService;
import com.eastfair.projectcore.service.ProjectDbService;
import com.eastfair.boot.service.SuperCacheServiceImpl;
import com.eastfair.cache.projectcore.ProjectDbCacheKeyBuilder;
import com.eastfair.core.base.R;
import com.eastfair.core.model.CacheKeyBuilder;
import com.eastfair.projectcore.vo.ProjectDbVo;
import com.eastfair.uid.baidu.rule.SnowFlakeRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.eastfair.core.base.R.SUCCESS_CODE;

/**
 * <p>
 * 业务实现类
 * 项目分库分表信息
 * </p>
 *
 * @author ligang
 * @date 2021-07-07
 */
@Slf4j
@Service
////@DS("#thread.tenant")
public class ProjectDbServiceImpl extends SuperCacheServiceImpl<ProjectDbMapper, ProjectDb> implements ProjectDbService {
//    @Autowired
//    SelfUidService selfUidService;

    @Autowired
    AuthServiceFeign authServiceFeign;


    @Autowired
    UserAccountServiceFeign userAccountServiceFeign;

    @Autowired
    RoleServiceFeign roleServiceFeign;

    @Autowired
    DataIsolationService dataIsolationService;

    @Autowired
    SnowFlakeRole snowFlakeRole;

    //设置缓存名称
    @Override
    public CacheKeyBuilder getCacheKeyBuilder() {
        return new ProjectDbCacheKeyBuilder();
    }

    /**
     * 处理新增相关处理
     *
     * @param model 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerSave(ProjectDb model) {
        model.setId(snowFlakeRole.findUidSimple());
        //雪花ID,不需要分库分表
//        SelfUidDto selfUidDto = new SelfUidDto();
//        selfUidDto.setDbSuffix(model.getDbSuffix());
//        selfUidDto.setTableSuffix(model.getTableSuffix());
//
//        model.setId(selfUidService.getUid(selfUidDto));
        return R.successDef();
    }


    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ProjectDb> modelList) {
        modelList.stream().forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }


    @Override
    public Long getSelfUid(Long projectId) {
//        SelfUidDto selfUidDto = new SelfUidDto();
//        if (projectId == null || projectId == 0) {
//            //随机给，目前没有字典表
//            selfUidDto.setDbSuffix(0);
//            selfUidDto.setTableSuffix(0);
//        } else {
//            //解析项目id
//            SelfUidDto selfUidDto1 = selfUidService.parseUid(projectId);
//            selfUidDto.setDbSuffix(selfUidDto1.getDbSuffix());
//            selfUidDto.setTableSuffix(selfUidDto1.getTableSuffix());
////            ProjectDb projectDb = getByIdCache(projectId);
////            if (projectDb != null) {
////                selfUidDto.setDbSuffix(projectDb.getDbSuffix());
////                selfUidDto.setTableSuffix(projectDb.getTableSuffix());
////            } else {
////                selfUidDto.setDbSuffix(0);
////                selfUidDto.setTableSuffix(0);
////            }
//        }
//        return selfUidService.getUid(selfUidDto);
//        return DefaultUidGenerator.getUid(DefaultUidGenerator.parseUid(projectId));
        return null;
    }

    @Override
    public List<Long> batGetSelfUid(Long projectId, int count) {
        List<Long> ids = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            ids.add(getSelfUid(projectId));
        }
        return ids;
    }

    @Override
//    @GlobalTransactional(name = "createProject", rollbackFor = Exception.class)
    public R createProject(ProjectDbDTO projectDbDTO) {
        ProjectDb projectDb = BeanUtil.toBean(projectDbDTO, getEntityClass());
        //添加
        save(projectDb);
        //生成组织
        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setName(projectDb.getName());
        organizationDTO.setResourceId(projectDb.getId());
        organizationDTO.setResourceType(ResourceOrganizationResourceTypeEnum.P);
        organizationDTO.setProjectId(projectDb.getId());
        //查询原有角色
        List<RoleVo> oldRoleVoList = null;
        R<List<RoleVo>> r = roleServiceFeign.findAllByIds(projectDbDTO.getRoleIds());
        if (r.getCode() == SUCCESS_CODE) {
            oldRoleVoList = r.getData();
        }
        //切换项目id到下个服务，慎用，之后需要还原
        ContextUtil.setProjectId(projectDb.getId());
        R<Organization> organizationR = authServiceFeign.createProject(organizationDTO);
        if (organizationR.getCode() == SUCCESS_CODE) {
            Long orgId = organizationR.getData().getId();
            //创建项目admin用户
            UserAccountDto userAccountDto = new UserAccountDto();
            userAccountDto.setProjectId(projectDb.getId());
            R<UserAccountVo> accountVoR = userAccountServiceFeign.addAdminUser(userAccountDto);
            if (accountVoR.getCode() == SUCCESS_CODE) {
                //用户管理员绑定到组织上
                UserOrganizationDTO userOrganizationDTO = new UserOrganizationDTO();
                userOrganizationDTO.setOrganizationId(orgId);
                userOrganizationDTO.setUserIds(Arrays.asList(accountVoR.getData().getId()));
                userOrganizationDTO.setProjectId(projectDb.getId());
                authServiceFeign.addUserOfOrg(userOrganizationDTO);
            }
        }
        return R.success(projectDb);
    }

    @Override
//    @GlobalTransactional(name = "createProject", rollbackFor = Exception.class)
    public R createAdminProject(ProjectDbDTO projectDbDTO) {
        ProjectDb projectDb = BeanUtil.toBean(projectDbDTO, getEntityClass());
        projectDb.setIsAdmin(BusinessConstant.YES);
        //添加
        save(projectDb);
        //切换项目id到下个服务，慎用，之后需要还原
        ContextUtil.setProjectId(projectDb.getId());
        //创建子系统
        List<DataIsolationVo> dataIsolationList = dataIsolationService.createSystem(projectDb.getId());

        //创建项目admin用户
        UserAccountDto userAccountDto = new UserAccountDto();

        userAccountDto.setIsP(BusinessConstant.YES);
        userAccountDto.setIsPVenue(BusinessConstant.YES);
        userAccountDto.setIsPCertificate(BusinessConstant.YES);
        userAccountDto.setIsPCompositeVenue(BusinessConstant.YES);
        userAccountDto.setIsPCompositeCourt(BusinessConstant.YES);

        userAccountDto.setIsPCompositeProducer(BusinessConstant.YES);
        userAccountDto.setIsPCompositeTransport(BusinessConstant.YES);
        userAccountDto.setIsPCompositeTrade(BusinessConstant.YES);
        userAccountDto.setIsPCompositeMating(BusinessConstant.YES);
        userAccountDto.setIsPPay(BusinessConstant.YES);
        userAccountDto.setIsPExhibitorSelf(BusinessConstant.YES);
        userAccountDto.setIsPCateringapp(BusinessConstant.YES);
        R<UserAccountVo> accountVoR = userAccountServiceFeign.addAdminUser(userAccountDto);

        for (DataIsolationVo dataIsolationVo : dataIsolationList) {
            //切换项目id到下个服务，慎用，之后需要还原
            ContextUtil.setSubSystemId(dataIsolationVo.getId());
            //生成子系统组织
            OrganizationDTO organizationDTO = new OrganizationDTO();
            organizationDTO.setName(projectDb.getName());
            organizationDTO.setResourceId(projectDb.getId());
            organizationDTO.setProjectId(projectDb.getId());
            organizationDTO.setSubsystemList(Arrays.asList(dataIsolationVo));

            R<Organization> organizationR = authServiceFeign.createProject(organizationDTO);
            if (organizationR.getCode() == SUCCESS_CODE) {
                //用户管理员绑定到组织上成为管理员
                UserOrganizationDTO userOrganizationDTO = new UserOrganizationDTO();
                userOrganizationDTO.setOrganizationId(organizationR.getData().getId());
                userOrganizationDTO.setUserIds(Arrays.asList(accountVoR.getData().getId()));
//                userOrganizationDTO.setProjectId(dataIsolationVo.getId());

                authServiceFeign.addUserOfOrg(userOrganizationDTO);
            }

        }


//        if (accountVoR.getCode() == SUCCESS_CODE) {
//            //用户管理员绑定到组织上
//            UserOrganizationDTO userOrganizationDTO = new UserOrganizationDTO();
////            userOrganizationDTO.setOrganizationId(orgId);
//            userOrganizationDTO.setUserIds(Arrays.asList(accountVoR.getData().getId()));
//            userOrganizationDTO.setProjectId(projectDb.getId());
//            authServiceFeign.addUserOfOrg(userOrganizationDTO);
//        }


//        if (organizationR.getCode() == SUCCESS_CODE) {
//            Long orgId = organizationR.getData().getId();
//            //创建项目admin用户
//            UserAccountDto userAccountDto = new UserAccountDto();
//            userAccountDto.setProjectId(projectDb.getId());
//            R<UserAccountVo> accountVoR = userAccountServiceFeign.addAdminUser(userAccountDto);
//            if (accountVoR.getCode() == SUCCESS_CODE) {
//                //用户管理员绑定到组织上
//                UserOrganizationDTO userOrganizationDTO = new UserOrganizationDTO();
//                userOrganizationDTO.setOrganizationId(orgId);
//                userOrganizationDTO.setUserIds(Arrays.asList(accountVoR.getData().getId()));
//                userOrganizationDTO.setProjectId(projectDb.getId());
//                authServiceFeign.addUserOfOrg(userOrganizationDTO);
//            }
//        }
        return R.success(projectDb);
    }


//    @Override
//    @GlobalTransactional(name = "initSubSystem", rollbackFor = Exception.class)
//    public R initSubSystem(ProjectDbDTO projectDbDTO) {
//        //创建子系统
//        List<DataIsolationVo> dataIsolationList = dataIsolationService.createSystem(projectDbDTO.getId());
//        //生成组织
//        OrganizationDTO organizationDTO = new OrganizationDTO();
//        organizationDTO.setName(projectDb.getName());
//        organizationDTO.setResourceId(projectDb.getId());
//        organizationDTO.setResourceType(ResourceOrganizationResourceTypeEnum.P);
//        organizationDTO.setProjectId(projectDb.getId());
//        organizationDTO.setSubsystemList(dataIsolationList);
//        //切换项目id到下个服务，慎用，之后需要还原
//        ContextUtil.setProjectId(projectDb.getId());
//        R<Organization> organizationR = authServiceFeign.createProject(organizationDTO);
//        if (organizationR.getCode() == SUCCESS_CODE) {
//            Long orgId = organizationR.getData().getId();
//            //创建项目admin用户
//            UserAccountDto userAccountDto = new UserAccountDto();
//            userAccountDto.setProjectId(projectDb.getId());
//            R<UserAccountVo> accountVoR = userAccountServiceFeign.addAdminUser(userAccountDto);
//            if (accountVoR.getCode() == SUCCESS_CODE) {
//                //用户管理员绑定到组织上
//                UserOrganizationDTO userOrganizationDTO = new UserOrganizationDTO();
//                userOrganizationDTO.setOrganizationId(orgId);
//                userOrganizationDTO.setUserIds(Arrays.asList(accountVoR.getData().getId()));
//                userOrganizationDTO.setProjectId(projectDb.getId());
//                authServiceFeign.addUserOfOrg(userOrganizationDTO);
//            }
//        }
//        return R.success(projectDb);
//    }


    @Override
    public R updAdminProject(ProjectDbDTO projectDbDTO) {
        log.info("tarce is " + ContextUtil.getTrace());
        ProjectDb projectDb = getByIdCache(projectDbDTO.getId());
        projectDb.setName("测试" + new Random().nextInt());
        updateById(projectDb);
        //生成组织
        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setName(projectDb.getName());
        organizationDTO.setResourceId(projectDb.getId());
        organizationDTO.setResourceType(ResourceOrganizationResourceTypeEnum.P);
        organizationDTO.setProjectId(projectDb.getId());
        //切换项目id到下个服务，慎用，之后需要还原
        ContextUtil.setProjectId(projectDb.getId());
        R<Organization> organizationR = authServiceFeign.updProjectOrganization(organizationDTO);

        log.info(JSONObject.toJSONString(organizationR));
        return null;
    }

    @Override
    public R updateProject(ProjectDbDTO projectDbDTO) {
        ProjectDb projectDb = getByIdCache(projectDbDTO.getId());
        if (projectDb == null) {
            return R.fail("更新失败");
        }
        projectDb.setName(projectDbDTO.getName());
        projectDb.setEnName(projectDb.getEnName());
        //更新
        updateById(projectDb);
        //替换projectId 全局id
        ContextUtil.setProjectId(projectDb.getId());
        //更新组织
        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setName(projectDb.getName());
        organizationDTO.setResourceId(projectDb.getId());
        organizationDTO.setResourceType(ResourceOrganizationResourceTypeEnum.P);
        organizationDTO.setProjectId(projectDb.getId());
        R<Organization> organizationR = authServiceFeign.updProjectOrganization(organizationDTO);
        if (organizationR.getCode() == SUCCESS_CODE) {
            Long orgId = organizationR.getData().getId();
            //重新将角色注入到项目组织
            OrganizationRoleDto orgRoleDto = new OrganizationRoleDto();
            orgRoleDto.setRoleIds(projectDbDTO.getRoleIds());
            orgRoleDto.setOrganizationId(orgId);
            orgRoleDto.setConduction(false);
            authServiceFeign.updOrgRole(orgRoleDto);
        }
        return R.success(projectDb);
    }

    @Override
    public ProjectDbVo getAndRoleById(Long id) {
        ProjectDb projectDb = getByIdCache(id);
        if (projectDb != null) {
            ProjectDbVo projectDbVo = doToVo(projectDb);
            //查询角色
            //替换projectId 全局id
            ContextUtil.setProjectId(projectDbVo.getId());
            R<List<Long>> r = authServiceFeign.queryRoleOfResourceId(projectDb.getId());
            if (r.getCode() == SUCCESS_CODE) {
                List<Long> roleIds = r.getData();
                projectDbVo.setRoleIds(roleIds);
            }
            return projectDbVo;
        }
        return null;
    }

    @Override
    public ProjectDbVo queryExhibition(Long projectId) {
        ProjectDb projectDb = getByIdCache(projectId);
        if (projectDb != null) {
            ProjectDbVo projectDbVo = doToVo(projectDb);
            return projectDbVo;
        }
        return null;
    }

    @Override
    public R trasactionTest(ProjectDbDTO projectDbDTO) {
        ProjectDb projectDb = BeanUtil.toBean(projectDbDTO, getEntityClass());
        //添加
        updateById(projectDb);
        //生成组织
        OrganizationDTO organizationDTO = new OrganizationDTO();
        organizationDTO.setName(projectDb.getName());
        organizationDTO.setResourceId(projectDb.getId());
        organizationDTO.setResourceType(ResourceOrganizationResourceTypeEnum.P);
        organizationDTO.setProjectId(projectDb.getId());
        authServiceFeign.trasactionTest(organizationDTO);
        int i = 1 / 0;
        return R.success(projectDb);
    }

    public ProjectDbVo doToVo(ProjectDb projectDb) {
        if(projectDb==null){
            return null;
        }
        ProjectDbVo projectDbVo = new ProjectDbVo();
        BeanUtils.copyProperties(projectDb, projectDbVo);
        projectDbVo.setId(projectDb.getId());
        return projectDbVo;
    }

    public List<ProjectDbVo> doToVos(List<ProjectDb> projectDbList) {
        if (projectDbList == null || projectDbList.isEmpty()) {
            return null;
        }
        List<ProjectDbVo> result = new ArrayList<>();
        for (ProjectDb projectDb : projectDbList) {
            result.add(doToVo(projectDb));
        }
        return result;
    }

}
